﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace DARE
{
    [AttrTypeDependentSerializable(typeof(CVerticalScrollBarData))]
    public class CVerticalScrollBar : CScrollBar
    {

        #region properties

        /// <summary>
        /// If the value is between 0 and 1, the position is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// The value is relative to its parent.
        /// </summary>
        public override Vector2 Position
        {
            get
            {
                return base.Position;
            }
            set
            {
                base.Position = value;
                Actualize();
            }
        }

        /// <summary>
        /// If the value is between 0 and 1, the size is a percentage of the size of the parent
        /// (if the parent is null, the value is a percentage of the window).
        /// Else, the value is absolute.
        /// </summary>
        public override Vector2 Size
        {
            get
            {
                return base.Size;
            }
            set
            {
                base.Size = value;
                Actualize();
            }
        }

        /// <summary>
        /// Gets/Sets the rectangle where the widget will be draw.
        /// This value is automatically set when the position and/or the size are set.
        /// If you plan to use a different rectangle than the one automatically created,
        /// we recommand you to use the UseDrawableRect and DrawableRect properties.
        /// </summary>
        /// <seealso cref="UseDrawableRect"/>
        /// <seealso cref="DrawableRect"/>
        public override Rectangle Rect
        {
            get
            {
                return base.Rect;
            }
            set
            {
                base.Rect = value;
                Actualize();
            }
        }

        #endregion

        #region actualize

        /// <summary>
        /// Actualizes the widget.
        /// If anything has changed, it will allow this widget to get back its parameters.
        /// For example, if the size of the widget is a percentage of the size of its parent,
        /// if the parent's size changes, it will recalculate the good size of this widget.
        /// (This method is called automatically but you can force a new actualization).
        /// </summary>
        public override void Actualize()
        {
            base.Actualize();
            updateSliderPos();
            if (m_texture.Top != null)
                m_lessButton.Size = new Vector2(m_texture.Rectangle.Width, m_texture.Top.Value.Value.Height);
            if (m_texture.Bottom != null)
                m_moreButton.Size = new Vector2(m_texture.Rectangle.Width, m_texture.Bottom.Value.Value.Height);
            m_moreButton.Rect = new Rectangle(m_rect.X, m_rect.Y + m_rect.Height - m_moreButton.Rect.Height, m_rect.Width, m_rect.Width);
        }

        #endregion

        #region ctor

        public CVerticalScrollBar(CHUDSystem hud, CWidget parent, string name)
            : base(hud, parent, name)
        {
            m_texture = HUD.Skinner.GetTexture("verticalscrollbar");

            m_lessButton.Texture = HUD.Skinner.GetTexture("verticalscrollbarlessbuttonreleased");
            m_lessButton.Size = new Vector2(m_texture.Rectangle.Width, m_texture.Top.Value.Value.Height);
            m_lessButton.ReleasedTexture = HUD.Skinner.GetTexture("verticalscrollbarlessbuttonreleased");
            m_lessButton.ClickedTexture = HUD.Skinner.GetTexture("verticalscrollbarlessbuttonclicked");

            m_moreButton.Texture = HUD.Skinner.GetTexture("verticalscrollbarmorebuttonreleased");
            m_moreButton.Size = new Vector2(m_texture.Rectangle.Width, m_texture.Bottom.Value.Value.Height);
            m_moreButton.Position = new Vector2(0, m_rect.Height - m_moreButton.Rect.Height);
            m_moreButton.ReleasedTexture = HUD.Skinner.GetTexture("verticalscrollbarmorebuttonreleased");
            m_moreButton.ClickedTexture = HUD.Skinner.GetTexture("verticalscrollbarmorebuttonclicked");

            m_slider.Position = new Vector2(0, m_lessButton.Rect.Width);
            m_slider.Texture = HUD.Skinner.GetTexture("verticalscrollbarsliderreleased");
            m_slider.Size = new Vector2(m_rect.Width, m_rect.Width);
            m_slider.ReleasedTexture = HUD.Skinner.GetTexture("verticalscrollbarsliderreleased");
            m_slider.ClickedTexture = HUD.Skinner.GetTexture("verticalscrollbarsliderclicked");

            Size = new Vector2(20, 200);
        }

        #endregion

        #region update/draw

        /// <summary>
        /// Called automatically.
        /// Used to update the slider position.
        /// </summary>
        public override void updateSliderPos()
        {
            Rectangle r = m_slider.Rect;
            float tmp = m_value * (m_rect.Height - (2 * m_rect.Width) - m_slider.Rect.Height) / 100.0f;
            r.Y = (int)((m_rect.Y + tmp) + m_rect.Width);
            if (r.Y < m_rect.Y + m_rect.Width)
                r.Y = m_rect.Y + m_rect.Width;
            r.X = m_rect.X + (int)m_margins.Left;
            r.Width = (int)(m_rect.Width - m_margins.Left - m_margins.Right);
            r.Height = (int)(m_rect.Width - m_margins.Left - m_margins.Right);
            m_slider.Rect = r;
        }

        protected override float getRelativeMousePos(CMouse mouse)
        {
            if (mouse.Position.Y - (m_slider.Rect.Height / 2) < m_rect.Y + m_rect.Width)
                return 0;
            if (m_slider.Rect.Height >= m_rect.Height - (2 * m_rect.Width))
                return 0;
            if (mouse.Position.Y + (m_slider.Rect.Height / 2) > m_rect.Y + m_rect.Height - m_rect.Width)
                return 100;
            float ret = ((mouse.Position.Y - m_rect.Y - m_rect.Width - (m_slider.Rect.Height / 2.0f)) * 100.0f / (m_rect.Height - (2.0f * m_rect.Width) - m_slider.Rect.Height));
            if (ret > 100)
                return 100;
            else if (ret < 0)
                ret = 0;
            return ret;
        }
        
        public override bool Update(GameTime gameTime)
        {
            double timeSinceLastRepeat = gameTime.TotalGameTime.TotalMilliseconds - m_lastRepeated;
            if (m_slider.IsLeftClicked)
            {
                m_value = getRelativeMousePos(CDare.Instance.InputMgr.Mouse);
                m_slider.Texture.Rectangle = m_slider.Rect;
                updateSliderPos();
            }
            else if (m_isLessClicked && timeSinceLastRepeat > m_repeatInterval)
            {
                m_lessButton.InvokeClick(m_lessButton);
                m_lastRepeated = gameTime.TotalGameTime.TotalMilliseconds;
                if (m_repeatEnabled)
                    m_repeatInterval = 50;
                else
                    m_repeatEnabled = true;
            }
            else if (m_isMoreClicked && timeSinceLastRepeat > m_repeatInterval)
            {
                m_moreButton.InvokeClick(m_moreButton);
                m_lastRepeated = gameTime.TotalGameTime.TotalMilliseconds;
                if (m_repeatEnabled)
                    m_repeatInterval = 50;
                else
                    m_repeatEnabled = true;
            }
            return base.Update(gameTime);
        }

        #endregion
    }
}
